﻿using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FibonacciAsynchronous
{
   public partial class AsynchronousTestForm : Form
   {
      public AsynchronousTestForm()
      {
         InitializeComponent();
      } 

      private async void startButton_Click( object sender, EventArgs e )
      {
         outputTextBox.Text = "Starting Task to calculate Fibonacci(46)\r\n";

         Task< TimeData > task1 = Task.Run( () => StartFibonacci( 46 ) );

         outputTextBox.AppendText("Starting Task to calculate Fibonacci(45)\r\n" );
                     
         Task< TimeData > task2 = Task.Run( () => StartFibonacci( 45 ) );
         
         await Task.WhenAll( task1, task2 ); 
         
         DateTime startTime = 
            ( task1.Result.StartTime < task2.Result.StartTime ) ? 
            task1.Result.StartTime : task2.Result.StartTime;

         
         DateTime endTime = 
            ( task1.Result.EndTime > task2.Result.EndTime ) ? 
            task1.Result.EndTime : task2.Result.EndTime;

         
         outputTextBox.AppendText( String.Format(
            "Total calculation time = {0:F6} minutes\r\n",
            endTime.Subtract( startTime ).TotalMilliseconds / 60000.0 ) );
      }

      
      TimeData StartFibonacci( int n )
      {
         
         TimeData result = new TimeData();

         AppendText( String.Format( "Calculating Fibonacci({0})", n ) );

         result.StartTime = DateTime.Now;
         long fibonacciValue = Fibonacci( n ); 
         result.EndTime = DateTime.Now;

         AppendText( String.Format( "Fibonacci({0}) = {1}", n, fibonacciValue ) );
         AppendText( String.Format( 
            "Calculation time = {0:F6} minutes\r\n",
            result.EndTime.Subtract(result.StartTime ).TotalMilliseconds / 60000.0 ) );

         return result;
      }

      public long Fibonacci( long n )
      {
         if ( n == 0 || n == 1 )
            return n;
         else
            return Fibonacci( n - 1 ) + Fibonacci( n - 2 );
      } 
      
      public void AppendText( String text )
      {
         if ( InvokeRequired ) 
            Invoke( new MethodInvoker( () => AppendText( text ) ) );
         else 
            outputTextBox.AppendText( text + "\r\n" );
      } 
   } 
} 

